package com.xmtlxx.framework.interceptor;

import java.lang.reflect.Field;
import java.sql.Connection;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.mapping.StatementType;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.springframework.util.ReflectionUtils;
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;

@Intercepts(@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class}))
public class LastNullInterceptor implements Interceptor {

    private static final String DESC = "DESC";
    private static final String ASC = "ASC";
    private static final String REPLACE_DESC = "DESC NULLS LAST";
    private static final String REPLACE_ASC = "ASC NULLS LAST";

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        StatementHandler handler = PluginUtils.realTarget(invocation.getTarget());
        MetaObject metaObject = SystemMetaObject.forObject(handler);

        // 判断是不是SELECT操作，跳过存储过程
        MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
        if (SqlCommandType.SELECT != mappedStatement.getSqlCommandType()
                || StatementType.CALLABLE == mappedStatement.getStatementType()) {
            return invocation.proceed();
        }

        BoundSql boundSql = handler.getBoundSql();
        String sql = boundSql.getSql().toUpperCase();

        if (sql.contains("ORDER BY")) {
            sql = this.replaceWithRegex(sql);

            Field sqlField = boundSql.getClass().getDeclaredField("sql");
            ReflectionUtils.makeAccessible(sqlField);
            ReflectionUtils.setField(sqlField, boundSql, sql);
        }

        return invocation.proceed();
    }

    /**
     * 使用正则表达式精确替换排序关键字
     */
    private String replaceWithRegex(String sql) {
        // 匹配 ORDER BY 子句中的 DESC
        String descPattern = "\\b(DESC)\\b(?!\\s+NULLS\\s+LAST)";
        sql = sql.replaceAll(descPattern, REPLACE_DESC);

        // 匹配 ORDER BY 子句中的 ASC
        String ascPattern = "\\b(ASC)\\b(?!\\s+NULLS\\s+LAST)";
        sql = sql.replaceAll(ascPattern, REPLACE_ASC);

        return sql;
    }
}
